package com.platform.qujia.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.platform.qujia.config.BasicInfo;
import com.platform.qujia.constantEnum.DecimalConstant;
import com.platform.qujia.constantEnum.PayWayPayTypeEnum;
import com.platform.qujia.constantEnum.TianQuetechPayEnum;
import com.platform.qujia.dao.*;
import com.platform.qujia.enums.*;
import com.platform.qujia.enums.BalanceTypeEnum;
import com.platform.qujia.enums.PayWayServiceChargeEnum;
import com.platform.qujia.enums.PayWayUseTypeEnum;
import com.platform.qujia.enums.PhysicalCardPaymentEnum;
import com.platform.qujia.handle.PayOrderHandle;
import com.platform.qujia.param.request.PhysicalCardPosRechargeReq;
import com.platform.qujia.param.request.TradeReverseScanPayParameter;
import com.platform.qujia.param.request.YunHuaPayParam;
import com.platform.qujia.param.request.YunHuaPayPayParams;
import com.platform.qujia.param.response.YunhuaPayRes;
import com.platform.qujia.param.response.YunhuaResponse;
import com.platform.qujia.pay.PayChannelHandler;
import com.platform.qujia.pay.PaymentStrategy;
import com.platform.qujia.pay.QueryOrderStrategy;
import com.platform.qujia.pay.strategy.YunhuaChannel;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.PhysicalCardIntegralDto;
import com.platform.qujia.pojo.dto.PhysicalCardOrderDto;
import com.platform.qujia.pojo.dto.ScanOrderDTO;
import com.platform.qujia.pojo.vo.CardRechargeOrderPrintVO;
import com.platform.qujia.service.*;
import com.platform.qujia.utils.CodeMsg;
import com.platform.qujia.utils.RSASignature;
import com.platform.qujia.utils.SXFPaySign;
import com.platform.qujia.utils.exception.CustomException;
import com.yunhua.oil.common.core.utils.SpringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @date 2023/12/7
 */
@Service
public class PhysicalCardServiceImpl extends ServiceImpl<PhysicalCardMapper,PhysicalCard> implements PhysicalCardService {

    private static final Logger log = LoggerFactory.getLogger(PhysicalCardServiceImpl.class);

    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private PhysicalCardBalanceService physicalCardBalanceService;
    @Autowired
    private PayWayMapper payWayMapper;
    @Autowired
    private PayChannelHandler payChannelHandler;
    @Autowired
    private GzhNewsTemplateService gzhNewsTemplateService;
    @Autowired
    private CardBatchService cardBatchService;

    @Autowired
    private PhysicalCardMapper physicalCardMapper;

    @Autowired
    private AppUserInfoService appUserInfoService;

    @Autowired
    private PayOrderService payOrderService;

    @Resource
    private IntegralRuleService integralRuleService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Resource
    private StaOilGunMapper staOilGunMapper;

    @Resource
    private StationMapper stationMapper;

    @Resource
    private OilMapper oilMapper;

    @Resource
    private PayOrderMapper payOrderMapper;

    @Resource
    private CouponActivityService couponActivityService;

    @Resource
    private ReductionActivityBalanceRecordService reductionActivityBalanceRecordService;

    @Resource
    private ReductionActivityService reductionActivityService;


    @Value("${domain.payName}${server.servlet.context-path}/payment/stk/callback/sxf")
    private String sxfCallbackUrl;
    @Value("${domain.payName}${server.servlet.context-path}/payment/stk/callback/yh")
    private String yhCallbackUrl;
    private String publicKey;

    @Value("${spring.profiles.active}")
    public void setProfile(String profile){
        if (StringUtils.contains(profile,"prod")) {
            publicKey = SXFPaySign.sxfPublic;
        }else{
            publicKey = SXFPaySign.sxfTestPublic;
        }
    }

    public static final String PHYSICAL_CARD_PAYMENT_METHOD="dkq";

    @Override
    public ScanOrderDTO physicalCardScanRecharge(PhysicalCardPosRechargeReq req) {
        log.info("实体卡扫码充值---入参:{}",req);
        req.setCardNo(StringUtils.trim(req.getCardNo()));
        if (StringUtils.isBlank(req.getCardNo())) {
            throw new CustomException("卡号为空");
        }
        PayWay payWayForm=new PayWay();
        payWayForm.setUseType(PayWayUseTypeEnum.RECHARGE.getValue().toString());             //使用类型
        payWayForm.setStationId(req.getStationId());
        payWayForm.setAppType(PayWayServiceChargeEnum.APPTYPE_WECHAT.getValue().toString());
        PayWay payWay = payWayMapper.getOneStationPayWay(payWayForm); //获取该油站的支付类型，默认找微信的
        if (payWay == null || payWay.getServiceCharge() == null) {
            // 找不到查找支付宝的
            payWayForm.setAppType(PayWayServiceChargeEnum.APPTYPE_ALIPAY.getValue().toString());
            payWay = payWayMapper.getOneStationPayWay(payWayForm);
        }
        if (payWay == null || payWay.getServiceCharge() == null) {
            throw new CustomException("找不到支付渠道");
        }
        // 创建订单
        PhysicalCardBalance order = createOrder(req,payWay);
        PayWayPayTypeEnum payTypeEnum = PayWayPayTypeEnum.getByValue(Integer.valueOf(payWay.getPayType()));
        PaymentStrategy strategy = payChannelHandler.getPaymentStrategy(payTypeEnum);
        try{
            Object preParam = null;
            if (payTypeEnum == PayWayPayTypeEnum.Pay_Type_Accompanying_payment) {
                TradeReverseScanPayParameter param=new TradeReverseScanPayParameter();
                param.setOrgId(BasicInfo.TRADE_REVERSE_PAY_ORGID);
                param.setReqId(req.getReqId());
                param.setTimestamp(req.getTimestamp());
                param.setMno(payWay.getMno());
                param.setOrdNo(order.getBalanceNo());
                param.setAuthCode(req.getAuthCode());
                param.setAmt(order.getAmount().toString());
                param.setSubject("POS机充值");
                param.setTrmIp(req.getTrmIp());
                param.setExtend("POS");
                param.setNotifyUrl(sxfCallbackUrl);
                preParam = param;
            }else if (payTypeEnum == PayWayPayTypeEnum.PAY_TYPE_CLOUD_HUA){
                YunHuaPayParam yunHuaPayParam = new YunHuaPayParam();
                yunHuaPayParam.setFmno(payWay.getMno());
                yunHuaPayParam.setClientOrderNo(order.getBalanceNo());
                yunHuaPayParam.setClientSerialNo(order.getBalanceNo());
                yunHuaPayParam.setUserId(YunhuaChannel.DEFAULT_USER_ID);

                yunHuaPayParam.setPayMode(2);
                yunHuaPayParam.setPayChannel("poly_scan");

                yunHuaPayParam.setTxnAmt(order.getAmount());
                yunHuaPayParam.setTxnDesc("pos扫码充值");

                YunHuaPayPayParams payParams = new YunHuaPayPayParams();

                payParams.setNotifyUrl(yhCallbackUrl);
                payParams.setAuthCode(req.getAuthCode());
                //机构号
//                String orgCode = stationEnterpriseCopInfoService.getOrgCode(StationEnterpriseCopInfoVo.builder()
//                        .stationId(String.valueOf(cardUseRecord.getStationId()))
//                        .enterpriseId(String.valueOf(cardUseRecord.getEnterpriseId())).build());
//                if(org.apache.commons.lang3.StringUtils.isNotBlank(orgCode)){
//                    payParams.setOrgCode(orgCode);
//                }
                yunHuaPayParam.setPayParams(JSONObject.toJSONString(payParams));
                preParam = yunHuaPayParam;
            }
            log.info("pos机实体卡充值调用第三方支付，渠道：{}",payTypeEnum.getKey());
            // 进行第三方支付调用
            Object result = strategy.doPay(null,null,payWay,preParam);
            if (result != null && payTypeEnum == PayWayPayTypeEnum.PAY_TYPE_CLOUD_HUA) {
                YunhuaResponse<YunhuaPayRes> response = (YunhuaResponse<YunhuaPayRes>) result;
                if (response.getData() != null) {
                    PhysicalCardBalance updated = new PhysicalCardBalance();
                    updated.setId(order.getId());
                    updated.setTransactionId(response.getData().getTransPayNo());
                    updated.setMerchantsNumber(response.getData().getTransInfoNo());
                    physicalCardBalanceService.updateById(updated);
                }
            }
            // 检查调用是否成功
            TianQuetechPayEnum payEnum = strategy.checkResult3(null, result);
            log.info("pos机实体卡充值调用第三方支付成功，渠道：{}，status:{}",payTypeEnum.getKey(),payEnum);
            ScanOrderDTO scanOrder = new ScanOrderDTO();
            scanOrder.setOrderNo(order.getBalanceNo());
            scanOrder.setStatus(payEnum);
            if (payEnum == TianQuetechPayEnum.PAY_SUCCESS) {
                // 免密同步返回成功，随行付不会回调上送地址，需手动回调
                if (result != null && payTypeEnum == PayWayPayTypeEnum.Pay_Type_Accompanying_payment) {
                    PhysicalCardServiceImpl bean = SpringUtils.getBean(PhysicalCardServiceImpl.class);
                    bean.asyncPcCallback((TradeReversePayInfo) result);
                }
            }
            return scanOrder;
        }catch (Exception e){
            log.info("调用第三方支付失败，渠道：{},ex:{}",payTypeEnum.getKey(),e.getMessage());
            if(e instanceof CustomException){
                throw e;
            }else{
                log.error(e.getMessage(),e);
                throw new CustomException("支付失败");
            }
        }
    }

    @Override
    public CardRechargeOrderPrintVO queryPhysicalCardScanOrder(TradeReverseScanPayParameter req) {
        log.info("实体卡扫码充值-订单查询---入参:{}",req);
        PhysicalCardBalance q = new PhysicalCardBalance();
        q.setBalanceNo(req.getOrdNo());
        QueryWrapper<PhysicalCardBalance> qw = new QueryWrapper<>(q);
        PhysicalCardBalance pcb = physicalCardBalanceService.getOne(qw);
        if (pcb == null) {
            throw new CustomException(CodeMsg.PAY_FAIL);
        }
        if (StringUtils.equals("1",pcb.getStatus())) {
            CardRechargeOrderPrintVO printVO = new CardRechargeOrderPrintVO();
            printVO.setOrderNo(pcb.getBalanceNo());
            printVO.setPhysicalCardNo(pcb.getPhysicalCardNo());
            printVO.setAmt(pcb.getAmount());
            printVO.setBalance(pcb.getBalanceAmount());
            printVO.setCreateTime(pcb.getCreateTime());
            printVO.setPayType(pcb.getPayment());
            if (pcb.getOperator() != null) {
                SysUser sysUser = sysUserMapper.selectByPrimaryKey(Long.valueOf(pcb.getOperator()));
                if (sysUser != null) {
                    printVO.setOperatorName(sysUser.getUserName());
                }
            }
            PhysicalCard f = new PhysicalCard();
            f.setPhysicalCardNo(pcb.getPhysicalCardNo());
            PhysicalCard one = getOne(new QueryWrapper<>(f));
            if (one != null) {
                printVO.setCustomerName(one.getUserName());
                printVO.setMobilePhone(one.getUserPhone());
                printVO.setCardOilsType(one.getCardType());
            }
            return printVO;
        }
        if(!StringUtils.equals("0",pcb.getStatus())){
            throw new CustomException(CodeMsg.PAY_FAIL);
        }
        Long payWayId = pcb.getPayWayId();
        PayWay payWay = payWayMapper.selectPayWayById(payWayId);
        if (payWay == null) {
            throw new CustomException("找不到支付渠道");
        }

        PayWayPayTypeEnum typeEnum = PayWayPayTypeEnum.getByValue(Integer.valueOf(payWay.getPayType()));

        QueryOrderStrategy strategy = payChannelHandler.getQueryOrderStrategy(typeEnum);
        log.info("查询支付状态，{}",typeEnum.getKey());
        TradePaymentRecordsDO record = new TradePaymentRecordsDO();
        record.setOrderSn(pcb.getBalanceNo());
        TianQuetechPayEnum orderStatus = strategy.getOrderStatus(req,record,payWay);
        log.info("查询支付状态结束，{}",typeEnum.getKey());
        if(orderStatus == TianQuetechPayEnum.PAY_SUCCESS || orderStatus == TianQuetechPayEnum.PAY_PAYING){
            throw new CustomException(typeEnum.getKey()+"-支付中",CodeMsg.TRADE_REVERSE_PAY_WAIT_MINUTE.getRetCode());
        }

        if(orderStatus == TianQuetechPayEnum.PAY_FAIL){
            PhysicalCardBalance updated = new PhysicalCardBalance();
            updated.setId(pcb.getId());
            updated.setStatus("2");
            physicalCardBalanceService.updateById(updated);
            throw new CustomException(typeEnum.getKey()+"-支付失败");
        }
        return null;
    }

    @Async
    public void asyncPcCallback(TradeReversePayInfo info){
        orderCallback(null,info.getOrdNo(),info.getPayTime(),false);
    }

    @Override
    @Transactional
    public String callbackSxf(Map<String, Object> request) {
        log.info("=====随行付实体卡充值回调--参数:{}",request);
        String sign = (String) request.remove("sign");
        String signContent = RSASignature.getOrderContent(request);
        if (!RSASignature.doCheck(signContent, sign, this.publicKey)) {
            log.info("=====随行付回调验签失败--参数:{}",request);
            return SxfCallbackServiceImpl.FAIL_RETURN_VALUE;
        }
        String ordNo = String.valueOf(request.get("ordNo"));
        if (StringUtils.isBlank(ordNo)) {
            log.info("=====订单号为空");
            return SxfCallbackServiceImpl.SUCCESS_RETURN_VALUE;
        }
        orderCallback(null,ordNo,"",false);
        return SxfCallbackServiceImpl.SUCCESS_RETURN_VALUE;
    }

    @Override
    public String callbackYh(Map<String, Object> request) {
        log.info("=====云化实体卡充值回调--参数:{}",request);
        String ordNo = (String) request.get("clientSerialNo");
        if (StringUtils.isBlank(ordNo)) {
            log.info("=====订单号为空");
            return YunhuaChannel.SUCCESS_RETURN_VALUE;
        }
        String status = String.valueOf(request.get("status"));
        if (!StringUtils.equals("3", status)) {
            log.info("=====云化实体卡充值回调--状态不对,ordNo:{},status:{}",ordNo,status);
            return YunhuaChannel.SUCCESS_RETURN_VALUE;
        }
        orderCallback(request,ordNo,"",true);
        return YunhuaChannel.SUCCESS_RETURN_VALUE;
    }

    private void orderCallback(Map<String, Object> request,String orderNo,String payTime,boolean yh){
        PhysicalCardBalance pcb = new PhysicalCardBalance();
        pcb.setBalanceNo(orderNo);
        QueryWrapper<PhysicalCardBalance> qw = new QueryWrapper<>(pcb);
        pcb = physicalCardBalanceService.getOne(qw);
        if (pcb == null) {
            log.info("=====实体卡充值回调--订单未找到:{}",orderNo);
            return;
        }
        PhysicalCard qc = new PhysicalCard();
        qc.setPhysicalCardNo(pcb.getPhysicalCardNo());
        QueryWrapper<PhysicalCard> qwc = new QueryWrapper<>(qc);
        PhysicalCard pcOne = getOne(qwc);
        if (pcOne == null) {
            log.info("=====实体卡充值回调--卡未找到,cardNo:{}",pcb.getPhysicalCardNo());
            return;
        }
        BigDecimal amount;
        PhysicalCard pcUpdate = new PhysicalCard();
        pcUpdate.setId(pcOne.getId());
        PhysicalCardBalance pcbUpdate = new PhysicalCardBalance();
        pcbUpdate.setId(pcb.getId());
        if(Objects.isNull(pcOne.getPhysicalCardAmount())
                || (pcOne.getPhysicalCardAmount().signum() == 0)){
            pcUpdate.setPhysicalCardAmount(pcb.getAmount());
            pcbUpdate.setBalanceAmount(pcb.getAmount());
        } else {
            amount = pcOne.getPhysicalCardAmount().add(pcb.getAmount());
            pcUpdate.setPhysicalCardAmount(amount);
            pcbUpdate.setBalanceAmount(amount);
        }
        pcbUpdate.setStatus("1");
        updateById(pcUpdate);
        physicalCardBalanceService.updateById(pcbUpdate);
        if (yh) {
            gzhNewsTemplateService.sendStkSettleInfo(pcb,request);
        }
    }

    private PhysicalCardBalance createOrder(PhysicalCardPosRechargeReq req, PayWay payWay){
        Station station = enterpriseService.selectStationById(req.getStationId());
        PhysicalCard qc = new PhysicalCard();
        qc.setPhysicalCardNo(req.getCardNo());
        QueryWrapper<PhysicalCard> qw = new QueryWrapper<>(qc);
        PhysicalCard one = getOne(qw);
        if (one == null || station == null || !StringUtils.contains(one.getStationId(),station.getStationId().toString())) {
            throw new CustomException("卡不存在");
        }
        CardBatch cardBatch = cardBatchService.getById(one.getBatchId());
        if (cardBatch == null || !StringUtils.equals("czk",cardBatch.getPhysicalCardType())) {
            throw new CustomException("非储值卡不能充值");
        }
        PhysicalCardBalance order = new PhysicalCardBalance();
        order.setBalanceNo(com.platform.qujia.utils.StringUtils.generateOrdNo());
        order.setPhysicalCardNo(req.getCardNo());
        order.setAmount(new BigDecimal(req.getAmt()));
        //BigDecimal balance = one.getPhysicalCardAmount().add(order.getAmount());
        //order.setBalanceAmount(balance);
        order.setBalanceType(BalanceTypeEnum.RECHARGE.getValue());
        order.setEnterpriseId(Long.valueOf(station.getEnterpriseId()));
        order.setEnterpriseName(station.getEnterprise().getEnterpriseName());
        order.setStationId(station.getStationId().toString());
        order.setStationName(station.getStationName());
        order.setStatus("0");
        order.setCreateTime(new Date());
        order.setIsDeleted("0");
        order.setPayment(PhysicalCardPaymentEnum.POS.getValue());
        order.setRefundStatus("1");
        order.setPayWayId(Long.valueOf(payWay.getPayWayId()));
        BigDecimal sc = order.getAmount().multiply(payWay.getServiceCharge()).multiply(DecimalConstant.O_001).setScale(2, RoundingMode.HALF_UP);
        order.setServiceCharge(sc);
        order.setOperator(req.getOilPersonnelId());
        physicalCardBalanceService.save(order);
        reductionActivityBalanceRecordService.createBalanceRecord(order.getAmount(),req.getCardNo(),Long.valueOf(station.getEnterpriseId()),"xj",station.getStationId().longValue());
        return order;
    }

    @Override
    public void physicalCardBindAppUser(String physicalCardNo, String userPhone, Integer appUserId) {
        PhysicalCard physicalCard = physicalCardMapper.selectByPhysicalCardNo(physicalCardNo);
        if(Objects.isNull(physicalCard)){
            throw new CustomException("储值卡不存在");
        }
        if(Objects.nonNull(physicalCard.getAppUserId())){
            throw new CustomException("此实体卡已经绑定会员，请勿重复绑定");
        }
        CardBatch cardBatch = cardBatchService.getById(physicalCard.getBatchId());
        if (Objects.isNull(cardBatch) || PhysicalCardTypeEnum.DEK.getValue().equals(cardBatch.getPhysicalCardType())) {
            throw new CustomException("定额卡不能充值");
        }
        if(Objects.isNull(physicalCard.getEnterpriseId())){
            throw new CustomException("储值卡未写卡");
        }
        if(StringUtils.isEmpty(physicalCard.getUserPhone()) || !physicalCard.getUserPhone().equals(userPhone)){
            throw new CustomException("储值卡预留手机号和输入手机号不一致");
        }
        AppUserInfo appUserInfo = new AppUserInfo();
        appUserInfo.setUserId(appUserId);
        AppUserInfo userInfo = appUserInfoService.getAppUserInfo(appUserInfo);
        if(Objects.isNull(userInfo)){
            throw new CustomException("会员不存在");
        }
        if(!physicalCard.getEnterpriseId().toString().equals(userInfo.getStationId().toString())){
            throw new CustomException("储值卡与会员不是同一油企，绑定失败");
        }
        physicalCard.setAppUserId(appUserId);
        physicalCard.setUpdateTime(new Date());
        int i = physicalCardMapper.updateByPrimaryKeySelective(physicalCard);
        if(i <= 0){
            throw new CustomException("储值卡绑定会员绑定失败");
        }
    }

    @Override
    public List<PhysicalCard> selectByPhysicalCardList(PhysicalCard physicalCard) {
        return physicalCardMapper.selectByPhysicalCardList(physicalCard);
    }

    @Override
    public PhysicalCard selectByPhysicalCardByNo(String physicalCardNo) {
        return physicalCardMapper.selectByPhysicalCardNo(physicalCardNo);
    }

    @Override
    public CardBatch selectCardBatchById(String batchId) {
        return cardBatchService.getById(batchId);
    }

    @Override
    public void physicalCardIntegral(PhysicalCardIntegralDto physicalCardIntegralDto) {
        if(Objects.isNull(physicalCardIntegralDto) || com.platform.qujia.utils.StringUtils.isEmpty(physicalCardIntegralDto.getPhysicalCardNo()) || com.platform.qujia.utils.StringUtils.isEmpty(physicalCardIntegralDto.getOrderNo())){
            log.info("实体卡消费产生积分参数不全,发送失败,physicalCardIntegralDto:[{}]",JSONObject.toJSONString(physicalCardIntegralDto));
            return;
        }
        PhysicalCard physicalCard = this.selectByPhysicalCardByNo(physicalCardIntegralDto.getPhysicalCardNo());
        if(Objects.isNull(physicalCard)){
            log.info("实体卡不存在，产生积分失败,physicalCardIntegralDto:[{}]",JSONObject.toJSONString(physicalCardIntegralDto));
            return;
        }

        if(Objects.isNull(physicalCard.getAppUserId())){
            log.info("实体卡未绑定会员，产生积分失败,physicalCard:[{}]",JSONObject.toJSONString(physicalCard));
            return;
        }

        AppUserInfo userInfo = new AppUserInfo();
        userInfo.setUserId(physicalCard.getAppUserId());
        AppUserInfo appUserInfo = appUserInfoService.getAppUserInfo(userInfo);
        if(Objects.isNull(appUserInfo)){
            log.info("实体卡产生积分会员不存在，产生积分失败,physicalCard:[{}]",JSONObject.toJSONString(physicalCard));
            return;
        }

        //积分推送
        PayOrder payOrder = payOrderService.selectOrderInfoByOrdNo(physicalCardIntegralDto.getOrderNo());
        CalculateIntegral calculateIntegral = new CalculateIntegral();
        calculateIntegral.setOilName(payOrder.getOilName());
        calculateIntegral.setStationId(payOrder.getStationId());
        calculateIntegral.setEnterpriseId(payOrder.getEnterpriseId());
        calculateIntegral.setOilId(payOrder.getOilId());
        calculateIntegral.setReceivableAmt(new BigDecimal(payOrder.getReceivableAmt().toString()));
        calculateIntegral.setOilLiters(new BigDecimal(payOrder.getOrderLiters()));
        calculateIntegral.setAmt(new BigDecimal(payOrder.getAmt().toString()));
        calculateIntegral.setUserId(payOrder.getConsumerId());

        CalculateIntegral calResult = integralRuleService.calUserIntegral(calculateIntegral);
        if(Objects.isNull(calResult) || (calResult.getIntegral() <= 0)){
            // 不推送积分
            return;
        }
        // 更新订单成长值
        payOrderService.updateGrowthValueByOrdNo(calResult.getGrowValue().longValue(),physicalCardIntegralDto.getOrderNo());

        // 更新会员积分记录
        appUserInfo.setIntegral(calResult.getIntegral() + appUserInfo.getIntegral());
        appUserInfo.setGrowUpValue(calResult.getGrowValue() + appUserInfo.getGrowUpValue());
        appUserInfoService.updateAppUserIntegral(appUserInfo);
        //生成积分记录
        calResult.setOrderNo(payOrder.getOrderNo());
        calResult.setNickName(appUserInfo.getBlogNickName());
        calResult.setMobilePhone(appUserInfo.getMobilePhone());
        integralRuleService.createIntegralRecord(calResult, PayTypeEnum.dkq.getType(), appUserInfo.getIntegral());
    }


    @Override
    @Transactional
    public PayOrder physicalCardConsumption(PhysicalCardOrderDto physicalCardOrderDto) {
        // 创建订单
        PayOrder payOrder = new PayOrder();
        BigDecimal receivableAmt = physicalCardOrderDto.getAmount();
        PhysicalCard physicalCard = this.selectByPhysicalCardByNo(physicalCardOrderDto.getPhysicalCardNo());
        if(Objects.isNull(physicalCard) || Objects.isNull(physicalCard.getEnterpriseId())
                || StringUtils.isEmpty(physicalCard.getStationId()) || Objects.isNull(physicalCardOrderDto.getConsumptionStationId())){
            throw new CustomException("实体卡不存在");
        }

        boolean isDek = false;
        SysUser sysUser = new SysUser();
        AppUserInfo appUserInfo = new AppUserInfo();
        //判断是定额卡还是储值卡
        if(this.physicalCardType(physicalCard)){
            isDek = true;
            physicalCardOrderDto.setBalanceType(BalanceTypeEnum.RATION_CONSUMPTION.getValue());
            physicalCardOrderDto.setPayment(PhysicalCardPaymentEnum.RATION_CONSUMPTION.getValue());
        }else {
            physicalCardOrderDto.setBalanceType(BalanceTypeEnum.CONSUMPTION.getValue());
            physicalCardOrderDto.setPayment(PhysicalCardPaymentEnum.STORED_CONSUMPTION.getValue());
            // 消费者
            AppUserInfo userInfo = new AppUserInfo();
            userInfo.setStationId(physicalCard.getEnterpriseId().intValue());
            userInfo.setMobilePhone(physicalCard.getUserPhone());
            appUserInfo = appUserInfoService.getAppUserInfo(userInfo);
            if(Objects.isNull(appUserInfo)) {
                sysUser = sysUserMapper.selectUserByPhoneNumber(physicalCard.getUserPhone(), physicalCard.getEnterpriseId());
            }
        }

        BigDecimal amount;
        // 获取油枪、油品信息
        StaOilGun stationOilGunDto = getOilGun(physicalCardOrderDto.getOilGun(), physicalCardOrderDto.getConsumptionStationId());

        // 通用卡只要是同油企下就可以使用，不用区分油站和油品
        Station station = stationMapper.selectStationById(physicalCardOrderDto.getConsumptionStationId().intValue());
        // 通用卡区分油站、不区分油品
        List<String> stationIdList = Arrays.stream(physicalCard.getStationId().split(",")).collect(Collectors.toList());
        if(!stationIdList.contains(String.valueOf(physicalCardOrderDto.getConsumptionStationId()))){
            throw new CustomException("不能在该油站消费");
        }
        // 消费额度下限
        if(Objects.nonNull(station.getPhysicalCardAmount()) && (physicalCard.getPhysicalCardAmount().subtract(physicalCardOrderDto.getAmount()).compareTo(station.getPhysicalCardAmount()) <0)){
            throw new CustomException("余额低于消费下限，请充值后再使用");
        }

        // 判断卡类型和油品对应类型
        if(!ElectronCardType.GENERIC.getKey().equals(physicalCard.getCardType())){
            Oil oil = oilMapper.selectOilById(Long.valueOf(stationOilGunDto.getOilId()));
            if(Objects.nonNull(oil) && StringUtils.isNotEmpty(oil.getCardType())
                    && !oil.getCardType().equals(physicalCard.getCardType())){
                throw new CustomException("实体卡类型与该油品不匹配");
            }
        }

        BigDecimal oilLiters = physicalCardOrderDto.getAmount().divide(stationOilGunDto.getOilStationPrice(), 4, BigDecimal.ROUND_HALF_UP); //加油升数
        //实付金额减立减金额
        payOrder.setReceivableAmt(physicalCardOrderDto.getAmount().doubleValue()); // 应收金额

        BigDecimal discountAmt = BigDecimal.ZERO;
        BigDecimal rCHReductionAmt = BigDecimal.ZERO;
        if (physicalCardOrderDto.getEnableDiscount() == null || physicalCardOrderDto.getEnableDiscount()) {
            //立减活动
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            ReductionActivitiesVO activitiesVO=new ReductionActivitiesVO();
            activitiesVO.setActivityUse("CSP");
            activitiesVO.setAmt(physicalCardOrderDto.getAmount());
            activitiesVO.setDateTime(sdf.format(new Date()));
            activitiesVO.setEnterpriseId(physicalCard.getEnterpriseId().intValue());
            activitiesVO.setOilId(stationOilGunDto.getOilId());
            activitiesVO.setOrderLiters(oilLiters.toString());
            activitiesVO.setStationId(physicalCardOrderDto.getConsumptionStationId().intValue());
            activitiesVO.setPaymentMethod(PHYSICAL_CARD_PAYMENT_METHOD);
            activitiesVO.setPhysicalCardOilType(physicalCard.getCardType());
            activitiesVO.setPhysicalCardType(isDek ? PhysicalCardTypeEnum.DEK.getValue() : PhysicalCardTypeEnum.CZK.getValue());
            discountAmt=payOrderService.reductionActivitiesAmountCalculation(activitiesVO,null).setScale(2, BigDecimal.ROUND_HALF_UP);
            Map<String, Object> rchReductionAmt = reductionActivityService.getRCHReductionAmt(physicalCardOrderDto.getPhysicalCardNo(), physicalCardOrderDto.getAmount(), physicalCardOrderDto.getConsumptionStationId(), stationOilGunDto.getOilId().longValue(), oilLiters.toString());
            rCHReductionAmt = (BigDecimal) rchReductionAmt.get("rCHReductionAmt");

            //实付金额减立减金额
            payOrder.setReceivableAmt(physicalCardOrderDto.getAmount().doubleValue()); // 应收金额
            BigDecimal amount1 = physicalCardOrderDto.getAmount();
            amount1=amount1.subtract(discountAmt).subtract(rCHReductionAmt).setScale(2, BigDecimal.ROUND_HALF_UP);
            if(amount1.compareTo(BigDecimal.ZERO)<1){
                amount1 = new BigDecimal(0.01).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
            physicalCardOrderDto.setAmount(amount1);
        }


        // 修改实体卡面额
        if(Objects.isNull(physicalCard.getPhysicalCardAmount())
                || (physicalCard.getPhysicalCardAmount().signum() == 0)
                || (physicalCard.getPhysicalCardAmount().compareTo(physicalCardOrderDto.getAmount()) < 0)){
            throw new CustomException("实体卡面额不足，充值");
        } else {
            // 计算消费后的余额
            amount = physicalCard.getPhysicalCardAmount().subtract(physicalCardOrderDto.getAmount());
            physicalCard.setPhysicalCardAmount(amount);
            this.updatePhysicalCard(physicalCard);
            physicalCardOrderDto.setBalanceAmount(amount);
        }

        //组装增加充值记录
        PhysicalCardBalance physicalCardBalance = new PhysicalCardBalance();
        BeanUtils.copyProperties(physicalCardOrderDto,physicalCardBalance);
        physicalCardBalance.setEnterpriseId(physicalCard.getEnterpriseId());
        physicalCardBalance.setEnterpriseName(physicalCard.getEnterpriseName());
        physicalCardBalance.setStationId(station.getStationId().toString());
        physicalCardBalance.setStationName(station.getStationName());
        physicalCardBalance.setRechargeDiscount(rCHReductionAmt);
        physicalCardBalance.setConsumptionDiscount(discountAmt);

        //订单立减活动优惠  可以判断这个字段 enableDiscount 判断是否参加优惠活动



        // 没有第三方渠道信息
//        PayWayForm payWayForm = getStationPosPayWay(physicalCardOrderDto.getConsumptionStationId());

        payOrder.setAmt(physicalCardOrderDto.getAmount().doubleValue());// 实收金额
        payOrder.setDiscountAmt(discountAmt.add(rCHReductionAmt).doubleValue());// 优惠金额
        payOrder.setDiscountCouponAmt(0d);// 优惠券金额
        payOrder.setConsumeDiscountAmt(discountAmt);
        payOrder.setRechargeDiscountAmt(rCHReductionAmt);
        // 计算渠道费  目前不用计算渠道费
//        calculatorChannelFee(newPayOrder,payWay,amt);

//        payOrder.setChannelFeePayer(payWayForm.getChannelFeePayer()); //没有渠道手续费支付方0司机/1油企
        payOrder.setServiceCharge(BigDecimal.ZERO); //费率
//        newPayOrder.setCommission(commission.doubleValue()); //渠道费 没有渠道费 默认为0

        String orderNo= com.platform.qujia.utils.StringUtils.generateOrdNo();
        payOrder.setOrderNo(orderNo);//订单号
        physicalCardBalance.setBalanceNo(orderNo); //实体卡消费时的订单号和订单表一致

        payOrder.setCustomerPhone(physicalCard.getUserPhone());
        if(Objects.nonNull(appUserInfo)){
            if(StringUtils.isNotEmpty(appUserInfo.getBlogNickName())) {
                payOrder.setConsumer(appUserInfo.getBlogNickName());
            }
            if(Objects.nonNull(appUserInfo.getUserId())){
                payOrder.setConsumerId(appUserInfo.getUserId());
            }
        }
        if(Objects.nonNull(sysUser)) {
            if(StringUtils.isNotEmpty(sysUser.getUserName())) {
                payOrder.setConsumer(sysUser.getUserName());
            }
            if(Objects.nonNull(sysUser.getUserId())){
                payOrder.setConsumerId(Integer.valueOf(sysUser.getUserId()));
            }
        }

        payOrder.setEnterpriseId(physicalCard.getEnterpriseId().intValue());
        payOrder.setEnterpriseName(physicalCard.getEnterpriseName());

        payOrder.setAppType(AppTypeEnum.POS.getValue()); // 支付容器：1微信2支付宝3pos机4双屏机
        payOrder.setPayType(PayTypeEnum.dkq.getType()); // 支付类型：wx,zfb,dzk,xj,yl,hyk,dkq
        payOrder.setOrderOriginType(OrderOriginTypeEnum.dkq.getValue()); //订单来源1小程序，2pos机，3双屏机

        payOrder.setStationName(station.getStationName());
        payOrder.setStationId(station.getStationId());                  //油站id
        //内部系统直接扣款
        payOrder.setStatus(PayOrderStatusEnum.PAY.getValue()); //创建订单 状态(0未支付，1，已支付)
        payOrder.setCreatedDate(new Date());           //创建时间
        payOrder.setPayDate(new Date());    // 支付时间不能为空，否则影响班结
        payOrder.setOilGun(physicalCardOrderDto.getOilGun()); //油枪号
        payOrder.setDzkAmt(0d);             //电子卡金额

        payOrder.setOilPirce(stationOilGunDto.getOilStationPrice().toString()); //油价 原价
        payOrder.setOrderType(stationOilGunDto.getOilClass()); // 油品类
        payOrder.setOilName(stationOilGunDto.getOilId().toString()); // 油品id


        payOrder.setOrderLiters(oilLiters.toString()); // 油升数
        payOrder.setOilPersonnelId(physicalCardOrderDto.getOilPersonnelId());//加油员id
//        payOrder.setPayWayId(payWayForm.getPayWayId());  // 没有第三方支付渠道
        payOrder.setUtmSource(UtmSourceEnum.OTHER.getValue());// 订单来源默认9   订单来源 1-扫码 9-其它
//        newPayOrder.setXJStatus(null);//小程序内现金支付：现金支付的状态（0申请1取消）

        log.info("实体卡创建消费记录physicalCardConsumption.physicalCardBalance：[{}]",JSONObject.toJSONString(physicalCardBalance));
        physicalCardBalanceService.addPhysicalCardBalance(physicalCardBalance); // 添加消费记录
        log.info("实体卡创建订单physicalCardConsumption.payOrder：[{}]",JSONObject.toJSONString(payOrder));
        PayOrderHandle.setPayOrderInvoiceStatus(payOrder);
        payOrderMapper.insertPayOrder(payOrder);  // 添加订单

        // 更新立减活动金额
        reductionActivityBalanceRecordService.updateBalance(receivableAmt,rCHReductionAmt,physicalCardOrderDto.getPhysicalCardNo());

//发券
        couponActivityService.physicalCardSendCoupon(payOrder);
        //打印小票
        payOrder.setOilName(stationOilGunDto.getOilName());
        gzhNewsTemplateService.feiePush(payOrder);

        payOrder.setBalance(amount);

        // 绑定会员的实体卡消费触发积分规则
        PhysicalCardIntegralDto physicalCardIntegralDto = new PhysicalCardIntegralDto();
        physicalCardIntegralDto.setPhysicalCardNo(physicalCard.getPhysicalCardNo());
        physicalCardIntegralDto.setOrderNo(orderNo);
        if(Objects.nonNull(physicalCard.getAppUserId())){
            // 绑定实体卡，计算积分
            this.physicalCardIntegral(physicalCardIntegralDto);
        }
        return payOrder;

    }

    private StaOilGun getOilGun(String oilGun,Long stationId){
        //油品价格
        StaOilGun staOilGun = new StaOilGun();
        staOilGun.setGunName(oilGun);    // 枪号
        staOilGun.setStationId(stationId.intValue());//油站id
        StaOilGun stationOilGun = staOilGunMapper.selectStaGunInfo(staOilGun);
        if(stationOilGun == null){
            throw new CustomException("创建订单失败，未找到油枪信息");
        }
        log.info("获取油枪信息physicalCardConsumption.newPayWayForm:[{}]",JSONObject.toJSONString(stationOilGun));
        return stationOilGun;
    }

    @Override
    public boolean physicalCardType(PhysicalCard physicalCard) {
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getBatchId())){
            return false;
        }
        CardBatch cardBatch = cardBatchService.selectCardBatchById(Long.valueOf(physicalCard.getBatchId()));
        if(Objects.isNull(cardBatch) || StringUtils.isEmpty(cardBatch.getPhysicalCardType())){
            return false;
        }
        if(PhysicalCardTypeEnum.DEK.getValue().equals(cardBatch.getPhysicalCardType())){
            return true;
        }
        return false;
    }

    @Override
    public int updatePhysicalCard(PhysicalCard physicalCard) {
        // 修改实体卡不允许充值
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            throw new CustomException("updatePhysicalCard覆盖实体卡信息请求参数异常");
        }

        physicalCard.setUpdateTime(new Date());
        log.info("修改实体卡，PhysicalCardServiceImpl.updatePhysicalCard: [{}]", JSONObject.toJSONString(physicalCard));
        return physicalCardMapper.updateByPrimaryKeySelective(physicalCard);
    }

}
